package ejb.contentManagement;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import entities.Excursion;
import entities.ExcursionAvailability;
import ejb.dto.ExcursionAvailabilityDTO;

@Stateless
public class ExcursionAvailabilityBean implements ExcursionAvailabilityMgr {
	
	@PersistenceContext
    private EntityManager em;
	
	/**
	 * Retrieve entity ExcursionAvailability from the associated Id
	 * @param id
	 * @return entity ExcursionAvailability associated to the <code>id</code>
	 */
	public ExcursionAvailability getExcursionAvailability(int id) {
		return em.find(ExcursionAvailability.class, id);
	}
	
	/**
	 * Retrieve all ExcursionAvailability entities
	 * @return all ExcursionAvailability entities
	 */
	public List<ExcursionAvailability> getAllExcursionAvailabilities() {
    	return em.createNamedQuery("ExcursionAvailability.findAll", ExcursionAvailability.class)
                .getResultList();
    }
	
	/**
	 * Retrieve entity ExcursionAvailability from the associated Id and convert it 
	 * to corresponding ExcursionAvailabilityDTO
	 */
	@Override
	public ExcursionAvailabilityDTO getExcursionAvailabilityDTO(int id) {
		return  convertToDTO(getExcursionAvailability(id));
    }
	
	/**
	 * Retrieve all ExcursionAvailability entities and convert them into 
	 * corresponding list of ExcursionAvailabilityDTO
	 */
	@Override
	public List<ExcursionAvailabilityDTO> getAllExcursionAvailabilitiesDTO() {
		List<ExcursionAvailability> list = getAllExcursionAvailabilities();
		List<ExcursionAvailabilityDTO> newList = new ArrayList<ExcursionAvailabilityDTO>();
		for(ExcursionAvailability obj : list) {
			newList.add(convertToDTO(obj));
		}
		return newList;
	}
	
	/**
	 * Retrieve all ExcursionAvailability entities associated to one excursion, and
	 * convert them into corresponding list of ExcursionAvailabilityDTO
	 */
	@Override
	public List<ExcursionAvailabilityDTO> getAllExcursionAvailabilitiesDTO(int excursionId){
		Excursion excursion = em.find(Excursion.class, excursionId);
		List<ExcursionAvailability> list = em.createNamedQuery("ExcursionAvailability.findByExcursion", ExcursionAvailability.class).setParameter("ex", excursion).getResultList();
		List<ExcursionAvailabilityDTO> newList = new ArrayList<ExcursionAvailabilityDTO>();
		for(ExcursionAvailability obj : list) {
			newList.add(convertToDTO(obj));
		}
		return newList;
	}
	
	/**
	 * Convert entity ExcursionAvailability (parameter <code>e</code>) into corresponding ExcursionAvailabilityDTO 
	 * @param e
	 * @return converted ExcursionAvailabilityDTO
	 */
	public static ExcursionAvailabilityDTO convertToDTO(ExcursionAvailability e) {
		if(e == null){
			return null;
		}
		ExcursionAvailabilityDTO dto = new ExcursionAvailabilityDTO();

		dto.setId(e.getId());
		dto.setFromDate(e.getFromDate());
		dto.setToDate(e.getToDate());
		dto.setRemaining(e.getRemaining());
		dto.setExcursionName(e.getExcursion().getName());
		dto.setExcursionPrice(e.getExcursion().getPrice());
		return dto;
	}
	
	/**
	 * Retrieve entity ExcursionAvailability from the associated Id and delete 
	 * the corresponding element from the database
	 */
	@Override
	@RolesAllowed({"ADMINS"})
	public boolean deleteExcursionAvailability(int id) {
		try{
			em.remove(em.find(ExcursionAvailability.class, id));
			em.flush();
		}
		//Catch exceptions in the delete operation from database
		catch(Exception e){
			return false;
		}
		return true;
	}
	
	/**
	 * Create entity ExcursionAvailability from corresponding ExcursionAvailabilityDTO 
	 * and update corresponding element in database
	 */
	@Override
	@RolesAllowed({"ADMINS"})
	public boolean updateExcursionAvailability(ExcursionAvailabilityDTO updatedExcursionAvailability) {
		if(updatedExcursionAvailability.getFromDate() == null ||
			updatedExcursionAvailability.getToDate() == null ||
			updatedExcursionAvailability.getFromDate().compareTo(updatedExcursionAvailability.getToDate()) > 0 ||
			updatedExcursionAvailability.getRemaining() < 0 ||
			updatedExcursionAvailability.getRemaining() > 20000)
			return false;
		try{
			em.merge(new ExcursionAvailability(updatedExcursionAvailability, em.find(Excursion.class, updatedExcursionAvailability.getExcursionId())));
			em.flush();
		}
		//Catch exceptions in the update operation of database
		catch(Exception e){
			return false;
		}
		return true;		
	}
	
	/**
	 * Create entity ExcursionAvailability from corresponding ExcursionAvailabilityDTO 
	 * and insert new corresponding element in database
	 */
	@Override
	@RolesAllowed({"ADMINS"})
	public boolean insertExcursionAvailability(ExcursionAvailabilityDTO newExcursionAvailability) {
		if(newExcursionAvailability.getFromDate() == null ||
			newExcursionAvailability.getToDate() == null ||
			newExcursionAvailability.getFromDate().compareTo(newExcursionAvailability.getToDate()) > 0 ||
			newExcursionAvailability.getRemaining() < 0 ||
			newExcursionAvailability.getRemaining() > 20000)
			return false;
		try{
			em.persist(new ExcursionAvailability(newExcursionAvailability, em.find(Excursion.class, newExcursionAvailability.getExcursionId())));
			em.flush();
		} 
		//catch exceptions in the insert operation in database
		catch(Exception e){
			return false;
		}
		return true;	
	}
	
}
